package com.harmonyos.cases.view;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.harmonyos.cases.bean.CategoryInfo;
import com.harmonyos.cases.bean.RepositoriesInfo;
import com.harmonyos.cases.bean.Result;
import com.harmonyos.cases.bean.TypeInfo;
import com.harmonyos.cases.constants.Constants;
import com.harmonyos.cases.listener.CodeListener;
import com.harmonyos.cases.listener.ImageLoaderListener;
import com.intellij.openapi.ui.ComboBox;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.ui.JBColor;
import com.intellij.ui.components.JBLabel;
import com.intellij.ui.components.JBList;
import com.intellij.ui.components.JBScrollPane;
import com.intellij.ui.components.JBTextField;
import com.intellij.util.ui.JBUI;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import javax.swing.*;
import javax.swing.border.Border;
import javax.swing.border.MatteBorder;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import java.awt.*;
import java.awt.event.*;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static com.harmonyos.cases.utils.InsertUtils.*;

public class PluginDialog extends DialogWrapper {

    private final List<TypeInfo> typeInfoList = new ArrayList<>();
    private final List<CategoryInfo> categoryInfoList = new ArrayList<>();

    private String selectedCategory;
    private String selectedType;

    private final Map<String, List<TypeInfo>> categoryMap = new HashMap<>();
    private final Map<String, List<RepositoriesInfo>> typeMap = new HashMap<>();

    private JTextPane typeDesTextArea;

    // 被选中的item位置
    private int selectPosition = -1;
    // 数据列表
    private final List<RepositoriesInfo> dataList = new ArrayList<>();

    private CodeListener codeListener;
    // 描述组件
    private JTextPane desLabel;

    DefaultListModel<TypeInfo> defaultListModel;
    // 图片下载线程
    private ImageLoaderWorker imageLoaderWorker;
    // 组件列表
    private JPanel componentPanel;
    // loading提示
    private JLabel loadingText;
    private JPanel loadingPanel;
    // Grid列表滑动组件
    private JBScrollPane jGridScrollPane;

    public void setCodeListener(CodeListener codeListener) {
        this.codeListener = codeListener;
    }

    public PluginDialog() {
        super(true); // use current window as parent
        setTitle(Constants.PLUGIN_TITLE);
        requestData();
        // 初始化 UI
        init();
    }

    /**
     * 请求在线数据
     */
    public void requestData() {
        try {
            String fileName = getFileNameFromUrl(Constants.CONFIG_PATH);
            File localFile = new File(getCacheDirectory(), fileName);
            URL url = new URL(Constants.CONFIG_PATH);
            InputStream in = url.openStream();
            Files.copy(in, localFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
            String config = Files.readString(localFile.toPath());
            ObjectMapper mapper = new ObjectMapper();
            List<Result> resultList = mapper.readValue(config, new TypeReference<>() {
            });

            for (Result result : resultList) {
                categoryInfoList.add(result.getCategory());
                List<TypeInfo> typeInfos = new ArrayList<>();
                for (int i = 0; i < result.getCategoryDetailList().size(); i++) {
                    typeInfos.add(result.getCategoryDetailList().get(i).getTypeInfo());
                    List<RepositoriesInfo> tempList = result.getCategoryDetailList().get(i).getRepositoriesInfoList();
                    while (tempList.size() <= 4) {
                        tempList.add(new RepositoriesInfo());
                    }
                    typeMap.put(result.getCategoryDetailList().get(i).getTypeInfo().getTypeName(), tempList);
                }
                categoryMap.put(result.getCategory().getCategoryName(), typeInfos);
            }

            selectedCategory = categoryInfoList.get(0).getCategoryName();
            typeInfoList.clear();
            typeInfoList.addAll(categoryMap.get(selectedCategory));

        } catch (RuntimeException | IOException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    protected @Nullable JComponent createCenterPanel() {

        // 初始化整体父组件
        JPanel panel = new JPanel();
        SpringLayout springLayout = new SpringLayout();
        panel.setLayout(springLayout);
        panel.setPreferredSize(new Dimension(1000, 800));
        panel.setMinimumSize(new Dimension(500, 250));
        panel.setBorder(BorderFactory.createEmptyBorder());
        panel.addMouseListener(new MouseAdapter() {
            @Override
            public void mousePressed(MouseEvent e) {
                super.mousePressed(e);
                e.getComponent().requestFocus();
            }
        });

        // 初始化title
        JLabel titlePane = new JLabel();
        titlePane.setText(Constants.PLUGIN_SUB_TITLE);
        springLayout.putConstraint(SpringLayout.WEST, titlePane, 10, SpringLayout.WEST, panel);
        panel.add(titlePane);


        // 初始化类型列表
        JBList<TypeInfo> typeList = getTypeList();
        springLayout.putConstraint(SpringLayout.NORTH, typeList, 10, SpringLayout.SOUTH, titlePane);
        springLayout.putConstraint(SpringLayout.WEST, typeList, 20, SpringLayout.WEST, panel);
        panel.add(typeList);

        // 竖向分割线
        JSeparator separatorVertical = new JSeparator(SwingConstants.VERTICAL);
        separatorVertical.setPreferredSize(new Dimension(2, Integer.MAX_VALUE));
        springLayout.putConstraint(SpringLayout.WEST, separatorVertical, 0, SpringLayout.EAST, typeList);
        springLayout.putConstraint(SpringLayout.NORTH, separatorVertical, 0, SpringLayout.NORTH, typeList);
        panel.add(separatorVertical);

        // 横向分割线
        JSeparator separatorHorizontal = new JSeparator(SwingConstants.HORIZONTAL);
        separatorHorizontal.setPreferredSize(new Dimension(Integer.MAX_VALUE, 2));
        springLayout.putConstraint(SpringLayout.SOUTH, separatorHorizontal, 0, SpringLayout.SOUTH, panel);
        panel.add(separatorHorizontal);

        ComboBox<CategoryInfo> categoryComboBox = new ComboBox<>();
        for (CategoryInfo categoryInfo : categoryInfoList) {
            categoryComboBox.addItem(categoryInfo);
        }
        springLayout.putConstraint(SpringLayout.WEST, categoryComboBox, 10, SpringLayout.EAST, separatorVertical);
        categoryComboBox.setPreferredSize(new Dimension(100, 30));

        categoryComboBox.addItemListener(itemEvent -> {
            if (itemEvent.getStateChange() == ItemEvent.SELECTED) {
                selectedCategory = ((CategoryInfo) itemEvent.getItem()).getCategoryName();
                defaultListModel.clear();
                defaultListModel.addAll(categoryMap.get(selectedCategory));
                typeList.setModel(defaultListModel);
                typeList.setSelectedIndex(0);
            }
        });

        panel.add(categoryComboBox);

        // 初始化类型简介
        typeDesTextArea = new JTextPane();
        typeDesTextArea.setEditable(false);
        typeDesTextArea.setDisabledTextColor(new JBColor(new Color(0, 0, 0, 0), new Color(0, 0, 0, 0)));
        typeDesTextArea.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
        typeDesTextArea.setFont(typeDesTextArea.getFont().deriveFont(12f));
        springLayout.putConstraint(SpringLayout.SOUTH, typeDesTextArea, -5, SpringLayout.NORTH, separatorHorizontal);
        springLayout.putConstraint(SpringLayout.EAST, typeDesTextArea, -5, SpringLayout.WEST, separatorVertical);
        springLayout.putConstraint(SpringLayout.WEST, typeDesTextArea, 20, SpringLayout.WEST, panel);
        springLayout.putConstraint(SpringLayout.NORTH, typeDesTextArea, 30, SpringLayout.SOUTH, typeList);
        panel.add(typeDesTextArea);

        // 初始化搜索框
        JBTextField searchTextField = new JBTextField();
        searchTextField.getEmptyText().setText(Constants.PLUGIN_SEARCH);
        searchTextField.getEmptyText().setFont(searchTextField.getEmptyText().getComponent().getFont().deriveFont(12f));
        searchTextField.setColumns(10);
        springLayout.putConstraint(SpringLayout.EAST, searchTextField, -10, SpringLayout.EAST, panel);
        springLayout.putConstraint(SpringLayout.NORTH, searchTextField, 0, SpringLayout.NORTH, separatorVertical);
//        searchTextField.addKeyListener(new KeyAdapter() {
//            String inputText = "";
//
//            @Override
//            public void keyTyped(KeyEvent e) {
//                super.keyTyped(e);
//                System.out.println(e.getKeyChar());
//                inputText = inputText + e.getKeyChar();
//                dataList.clear();
//                String text = inputText;
//                if (text != null && !text.isEmpty()) {
//                    List<TypeInfo> types = categoryMap.get(selectedCategory);
//                    for (TypeInfo type : types) {
//                        List<RepositoriesInfo> repository = typeMap.get(type.getTypeName());
//                        for (RepositoriesInfo repositoriesInfo : repository) {
//                            if (repositoriesInfo.getName().contains(text)) {
//                                dataList.add(repositoriesInfo);
//                            }
//                        }
//                    }
//                    while (dataList.size() <= 4) {
//                        dataList.add(new RepositoriesInfo());
//                    }
//                    loadRepositoryList();
//                } else {
//                    dataList.addAll(typeMap.get(selectedType));
//                    loadRepositoryList();
//                }
//            }
//
//            @Override
//            public void keyReleased(KeyEvent e) {
//                super.keyReleased(e);
////                System.out.println(e.getKeyCode());
//            }
//        });
//        panel.add(searchTextField);

//        JBList<RepositoriesInfo> jbList = new JBList<>(dataList);
//        jbList.setLayoutOrientation(JBList.HORIZONTAL_WRAP);

        desLabel = new JTextPane();
        JScrollPane desScrollPane = new JBScrollPane(desLabel);
        desLabel.setFont(desLabel.getFont().deriveFont(12f));
        desLabel.setEditable(false);
        desLabel.setDisabledTextColor(new JBColor(new Color(0, 0, 0, 0), new Color(0, 0, 0, 0)));
        desLabel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
        desLabel.setPreferredSize(new Dimension(300, 100));
        springLayout.putConstraint(SpringLayout.WEST, desScrollPane, 0, SpringLayout.EAST, separatorVertical);
        springLayout.putConstraint(SpringLayout.EAST, desScrollPane, 0, SpringLayout.EAST, panel);
        springLayout.putConstraint(SpringLayout.SOUTH, desScrollPane, 0, SpringLayout.NORTH, separatorHorizontal);
        desLabel.setVisible(false);
        panel.add(desScrollPane);

        typeList.setSelectedIndex(0);
        dataList.clear();
        dataList.addAll(typeMap.get(selectedType));

        // 初始化组件/三方库列表
        componentPanel = new JPanel();
        GridLayout gridLayout = new GridLayout();
        gridLayout.setColumns(3);
        gridLayout.setRows(dataList.size() % 3 == 0 ? dataList.size() / 3 : dataList.size() / 3 + 1);
        gridLayout.setColumns(3);
        gridLayout.setHgap(40);
        gridLayout.setVgap(20);
        componentPanel.setLayout(gridLayout);

        jGridScrollPane = new JBScrollPane(componentPanel);
        springLayout.putConstraint(SpringLayout.WEST, jGridScrollPane, 0, SpringLayout.EAST, separatorVertical);
        springLayout.putConstraint(SpringLayout.EAST, jGridScrollPane, 0, SpringLayout.EAST, panel);
        springLayout.putConstraint(SpringLayout.NORTH, jGridScrollPane, 0, SpringLayout.SOUTH, searchTextField);
        springLayout.putConstraint(SpringLayout.SOUTH, jGridScrollPane, 0, SpringLayout.NORTH, desScrollPane);
        componentPanel.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
        jGridScrollPane.setVisible(false);
        panel.add(jGridScrollPane);

        // 初始化loading
        loadingPanel = new JPanel(new GridBagLayout());
        springLayout.putConstraint(SpringLayout.WEST, loadingPanel, 0, SpringLayout.EAST, separatorVertical);
        springLayout.putConstraint(SpringLayout.EAST, loadingPanel, 0, SpringLayout.EAST, panel);
        springLayout.putConstraint(SpringLayout.NORTH, loadingPanel, 0, SpringLayout.SOUTH, searchTextField);
        springLayout.putConstraint(SpringLayout.SOUTH, loadingPanel, 0, SpringLayout.NORTH, separatorHorizontal);
        loadingText = new JLabel();
        GridBagConstraints constraints = new GridBagConstraints();
        constraints.anchor = GridBagConstraints.CENTER;
        constraints.weightx = 1.0;
        constraints.weighty = 1.0;
        constraints.insets = JBUI.emptyInsets();
        loadingPanel.add(loadingText, constraints);
        panel.add(loadingPanel);

        // 异步加载图片
        loadRepositoryList();

        typeList.setSelectedIndex(0);

        return panel;
    }

    private void loadRepositoryList() {
        if (componentPanel != null) {
            componentPanel.removeAll();
        }
        imageLoaderWorker = new ImageLoaderWorker(componentPanel, dataList);
        imageLoaderWorker.setImageLoaderListener(new ImageLoaderListener() {
            @Override
            public void progress(int progress) {
//                loadingText.setText("loading... " + progress + "%");
                loadingText.setText(String.format(Constants.PLUGIN_LOADING_PROGRESS, progress));
            }

            @Override
            public void done() {
                desLabel.setVisible(true);
                jGridScrollPane.setVisible(true);
                loadingPanel.setVisible(false);
            }
        });
        imageLoaderWorker.execute();
    }

    // 获取分类列表
    private @NotNull JBList<TypeInfo> getTypeList() {
        defaultListModel = new DefaultListModel<>();
        defaultListModel.addAll(typeInfoList);
        JBList<TypeInfo> typeList = new JBList<>(defaultListModel);
//        typeList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        typeList.setPreferredSize(new Dimension(200, 200));
        // 使用自定义item
        typeList.setCellRenderer((jList, value, index, isSelected, cellHasFocus) -> {
            JLabel label = new JLabel(value.getTypeDesc());
            label.setOpaque(true);
            label.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
            if (isSelected) {
                label.setBackground(typeList.getSelectionBackground());
                label.setForeground(typeList.getSelectionForeground());
            } else {
                label.setBackground(typeList.getBackground());
                label.setForeground(typeList.getForeground());
            }
            return label;
        });
        // 添加选中效果
        typeList.addListSelectionListener(listSelectionEvent -> {
            if (!listSelectionEvent.getValueIsAdjusting()) {
                if (!typeList.isEmpty()) {
                    if (typeList.getSelectedValue() != null) {
                        typeDesTextArea.setText(typeList.getSelectedValue().getTypeDetail());
                        selectedType = typeList.getSelectedValue().getTypeName();
                        if (imageLoaderWorker != null) {
                            dataList.clear();
                            dataList.addAll(typeMap.get(selectedType));
                            loadRepositoryList();
                        }
                    }
                }
            }
        });

        return typeList;
    }

    @Override
    protected void doOKAction() {
        if (selectPosition == -1) {
            super.doCancelAction();
            return;
        }
//        super.doOKAction();
        if (codeListener != null) {
            String selectPath = null;
            if (selectedCategory.equals(Constants.PLUGIN_CATEGORY_CASE)) {
                selectPath = openFileChooser(codeListener.getActionEvent().getProject());
            }
            codeListener.insertCode(selectedCategory, dataList.get(selectPosition).getCodeInfo(), selectPath);
        }
        super.doOKAction();
    }

    // 定义一个 SwingWorker 用于异步加载图片
    public class ImageLoaderWorker extends SwingWorker<List<RepositoriesInfo>, RepositoriesInfo> {
        private final JPanel gridPanel;
        private List<RepositoriesInfo> list;
        private ImageLoaderListener imageLoaderListener;

        public ImageLoaderWorker(JPanel gridPanel, List<RepositoriesInfo> list) {
            this.gridPanel = gridPanel;
            this.list = list;
        }

        public void setImageLoaderListener(ImageLoaderListener imageLoaderListener) {
            this.imageLoaderListener = imageLoaderListener;
        }

        public void setList(List<RepositoriesInfo> list) {
            this.list = list;
        }

        @Override
        protected List<RepositoriesInfo> doInBackground() {
            for (int i = 0; i < list.size(); i++) {
                RepositoriesInfo item = list.get(i);
                String fileName = getFileNameFromUrl(item.getImage());
                File localFile = new File(getCacheDirectory(), fileName);
                if (!localFile.exists()) {
                    try {
                        // 加载图片
                        URL url = new URL(item.getImage());
                        InputStream in = url.openStream();
                        Files.copy(in, localFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
                        item.setIcon(new ImageIcon(localFile.getAbsolutePath()));
                        // 将图片发布给 EDT 进行 UI 更新
                    } catch (Exception ignored) {

                    }
                }
                item.setIcon(new ImageIcon(localFile.getAbsolutePath()));
                publish(item);
                if (imageLoaderListener != null) {
                    imageLoaderListener.progress(i * 100 / list.size());
                }
            }
            return null;
        }


        @Override
        protected void process(List<RepositoriesInfo> chunks) {
            // 在 GridLayout 中显示已加载的图片
            for (RepositoriesInfo item : chunks) {
                JPanel gridItem = new JPanel(new BorderLayout());
                JLabel imageLabel = new JLabel();
                imageLabel.setVerticalAlignment(SwingConstants.CENTER);
                imageLabel.setHorizontalAlignment(SwingConstants.CENTER);
                imageLabel.setPreferredSize(new Dimension(180, 380));
                Image image = item.getIcon().getImage().getScaledInstance(180, 380, Image.SCALE_DEFAULT);
                imageLabel.setIcon(new ImageIcon(image));
                gridItem.add(imageLabel, BorderLayout.CENTER);

                JBLabel textLabel = new JBLabel(item.getName(), SwingConstants.CENTER);
                textLabel.setPreferredSize(new Dimension(180, 30));
                gridItem.add(textLabel, BorderLayout.SOUTH);
                gridItem.setBackground(null);
                gridItem.setBorder(BorderFactory.createEmptyBorder(5, 10, 5, 10));
                gridItem.setOpaque(false);

                gridItem.addMouseListener(new MouseAdapter() {
                    @Override
                    public void mousePressed(MouseEvent e) {
                        if (item.getName().isEmpty() && item.getId().isEmpty() && item.getImage().isEmpty()) {
                            return;
                        }
                        e.getComponent().requestFocus();
                        // 取消之前选中的项
                        for (Component comp : gridPanel.getComponents()) {
                            comp.setBackground(null);
                            ((JPanel) comp).setBorder(BorderFactory.createEmptyBorder(5, 10, 5, 10));
                        }

                        // 设置当前项为选中状态
                        MatteBorder outBorder = BorderFactory.createMatteBorder(2, 2, 2, 2, JBColor.BLUE);
                        Border inBorder = BorderFactory.createEmptyBorder(5, 10, 5, 10);
                        gridItem.setBorder(BorderFactory.createCompoundBorder(outBorder, inBorder));
                        selectPosition = list.indexOf(item);
                        desLabel.setText(list.get(selectPosition).getDescription());
                    }
                });

                gridPanel.add(gridItem);

            }
        }

        @Override
        protected void done() {
            super.done();

            gridPanel.revalidate();  // 重新布局
            gridPanel.repaint();     // 重新绘制

            if (imageLoaderListener != null) {
                imageLoaderListener.done();
            }
        }
    }
}